/*
 * 申请一整块内存，用来保存Token和Node。
 * 保证内存是清零的。
 * 好处是相邻的Token在内存中是连续的，
 * 遍历Token的时候会很快。
*/

#ifndef RED_SYSTEM_BUFFER_H
#define RED_SYSTEM_BUFFER_H

#include <llvm/Support/raw_ostream.h>
#include <vector>

template <typename T, unsigned ElementsPerChunk = 200000>
class Buffer
{
private:
    uint32_t Count;
    std::vector<T*> Chunks;
    T *Chunk;

    void addChunk() {
        Count = 0;
        Chunk = (T*)::calloc(ElementsPerChunk, sizeof(T));
        if (Chunk == nullptr) {
            llvm::errs() << "Buffer: allocation failed\n";
            ::exit(EXIT_FAILURE);
        }
        Chunks.push_back(Chunk);
    }

public:
    Buffer() : Count(0) {
        addChunk();
    };

    ~Buffer() {
        for (auto P : Chunks) {::free(P);}
    };

    T* alloc() {
        if (Count < ElementsPerChunk) {
            return &Chunk[Count++];
        } else {
            addChunk();
            return &Chunk[Count++];
        }
    }

    T* alloc(uint32_t size) {
        if (LLVM_UNLIKELY(Count + size > ElementsPerChunk))
            addChunk();
        auto ptr = Chunk + Count;
        Count += size;
        return ptr;
    }
};

#endif /* RED_SYSTEM_BUFFER_H */
